package zzzhc.image.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;

import org.joone.engine.Monitor;
import org.joone.engine.NeuralNetEvent;
import org.joone.engine.NeuralNetListener;

import zzzhc.image.model.AppModel;
import zzzhc.image.model.NNInputTableModel;
import zzzhc.image.model.NNTableModel;
import zzzhc.image.model.TrainerPanelModel;
import zzzhc.image.recognize.nn.NN;
import zzzhc.image.recognize.nn.NNInput;
import zzzhc.image.recognize.nn.NNRecognizer;
import zzzhc.image.recognize.nn.NNType;
import zzzhc.image.recognize.nn.TrainResult;

public class TrainerPanel extends JPanel implements NeuralNetListener {

	private static final long serialVersionUID = 1L;

	private JLabel jLabel = null;

	private JComboBox nnTypeComboBox = null;

	private JLabel jLabel1 = null;

	private JSpinner epochsSpinner = null;

	private JPanel jPanel = null;

	private JButton startButton = null;

	private JProgressBar nnProgressBar = null;

	private JScrollPane jScrollPane = null;

	private JTable jTable = null;

	private DefaultComboBoxModel comboModel;

	private TrainerPanelModel model = AppModel.getInstance()
			.getTrainerPanelModel(); // @jve:decl-index=0:

	private JLabel jLabel2 = null;

	private JSpinner learningRateSpinner = null;

	private NNTableModel nnTableModel = model.getNnTableModel();

	private NNInputTableModel nnInputTableModel = model.getNnInputTableModel();

	public TrainerPanelModel getModel() {
		return model;
	}

	/**
	 * This is the default constructor
	 */
	public TrainerPanel() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {

		this.setSize(600, 450);
		this.setLayout(new BorderLayout());
		this.add(getJSplitPane(), BorderLayout.CENTER);
	}

	/**
	 * This method initializes nnTypeComboBox
	 * 
	 * @return javax.swing.JComboBox
	 */
	private JComboBox getNnTypeComboBox() {
		if (nnTypeComboBox == null) {
			comboModel = new DefaultComboBoxModel();
			comboModel.addElement(NNType.SIGMOID);
			// comboModel.addElement(NNType.GAUSSIAN);
			// comboModel.addElement(NNType.WTA);
			nnTypeComboBox = new JComboBox(comboModel);

		}
		return nnTypeComboBox;
	}

	/**
	 * This method initializes epochsSpinner
	 * 
	 * @return javax.swing.JSpinner
	 */
	private JSpinner getEpochsSpinner() {
		if (epochsSpinner == null) {
			SpinnerNumberModel spinnerNumberModel = new SpinnerNumberModel(500,
					1, 1000000, 100);
			epochsSpinner = new JSpinner(spinnerNumberModel);
		}
		return epochsSpinner;
	}

	/**
	 * This method initializes jPanel
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel() {
		if (jPanel == null) {
			GridBagConstraints gridBagConstraints22 = new GridBagConstraints();
			gridBagConstraints22.gridy = 1;
			GridBagConstraints gridBagConstraints14 = new GridBagConstraints();
			gridBagConstraints14.gridx = 2;
			gridBagConstraints14.gridy = 1;
			GridBagConstraints gridBagConstraints8 = new GridBagConstraints();
			gridBagConstraints8.gridx = 1;
			gridBagConstraints8.gridy = 1;
			jPanel = new JPanel();
			jPanel.setLayout(new GridBagLayout());
			jPanel.add(getStartButton(), gridBagConstraints22);
			jPanel.add(getContinueButton(), gridBagConstraints8);
			jPanel.add(getPauseButton(), gridBagConstraints14);
		}
		return jPanel;
	}

	private void setNNControlState(boolean enable) {
		addNoiseButton.setEnabled(enable);
		randomButton.setEnabled(enable);
		resetInputButton.setEnabled(enable);
		outputButton.setEnabled(enable);
	}

	/**
	 * This method initializes startButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getStartButton() {
		if (startButton == null) {
			startButton = new JButton();
			startButton.setText("开始");
			startButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					model.getTrainerSetting().setEpochs(
							((Number) epochsSpinner.getValue()).intValue());
					model.getTrainerSetting()
							.setMomentum(
									((Number) momentumSpinner.getValue())
											.doubleValue());
					model.getTrainerSetting().setLearningRate(
							((Number) learningRateSpinner.getValue())
									.doubleValue());

					model.getNN().setTrainerSetting(model.getTrainerSetting());

					model.getNnTableModel().clearAll();

					startButton.setEnabled(false);
					continueButton.setEnabled(false);
					pauseButton.setEnabled(true);

					setNNControlState(false);

					finishedPatterns = 0;
					nnProgressBar.setMaximum(model.getTrainerSetting()
							.getEpochs());
					circleLabel.setText("0");
					errorRateLabel.setText("0%");

					new StartTrainThread().start();
				}
			});
		}
		return startButton;
	}

	/**
	 * This method initializes nnProgressBar
	 * 
	 * @return javax.swing.JProgressBar
	 */
	private JProgressBar getNnProgressBar() {
		if (nnProgressBar == null) {
			nnProgressBar = new JProgressBar();
		}
		return nnProgressBar;
	}

	private volatile int finishedPatterns = 0;

	private JScrollPane jScrollPane11 = null;

	private JTable nnInputTable = null;

	private JLabel jLabel3 = null;

	private JSpinner momentumSpinner = null;

	private JLabel jLabel4 = null;

	private JLabel jLabel5 = null;

	private JLabel circleLabel = null;

	private JLabel errorRateLabel = null;

	private JLabel jLabel8 = null;

	private JLabel jLabel6 = null;

	private JLabel timeLabel = null;

	/**
	 * This method initializes jScrollPane
	 * 
	 * @return javax.swing.JScrollPane
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setBorder(BorderFactory.createTitledBorder(null,
					"\u8f93\u51fa\u7ed3\u679c",
					TitledBorder.DEFAULT_JUSTIFICATION,
					TitledBorder.DEFAULT_POSITION, new Font("Dialog",
							Font.BOLD, 12), new Color(51, 51, 51)));
			jScrollPane.setViewportView(getJTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jTable
	 * 
	 * @return javax.swing.JTable
	 */
	private JTable getJTable() {
		if (jTable == null) {
			jTable = new JTable(nnTableModel);
		}
		return jTable;
	}

	/**
	 * This method initializes learningRateSpinner
	 * 
	 * @return javax.swing.JSpinner
	 */
	private JSpinner getLearningRateSpinner() {
		if (learningRateSpinner == null) {
			SpinnerNumberModel numberModel = new SpinnerNumberModel(0.40d,
					0.01d, 1.0d, 0.05);
			learningRateSpinner = new JSpinner(numberModel);
		}
		return learningRateSpinner;
	}

	/**
	 * This method initializes jScrollPane11
	 * 
	 * @return javax.swing.JScrollPane
	 */
	private JScrollPane getJScrollPane11() {
		if (jScrollPane11 == null) {
			jScrollPane11 = new JScrollPane();
			jScrollPane11.setBorder(BorderFactory.createTitledBorder(null,
					"\u8f93\u5165\u53c2\u6570",
					TitledBorder.DEFAULT_JUSTIFICATION,
					TitledBorder.DEFAULT_POSITION, new Font("Dialog",
							Font.BOLD, 12), new Color(51, 51, 51)));
			jScrollPane11.setViewportView(getNnInputTable());
		}
		return jScrollPane11;
	}

	/**
	 * This method initializes nnInputTable
	 * 
	 * @return javax.swing.JTable
	 */
	private JTable getNnInputTable() {
		if (nnInputTable == null) {
			nnInputTable = new JTable(nnInputTableModel);
			nnInputTable.setRowHeight(60);
			// nnInputTable.addMouseListener(new java.awt.event.MouseAdapter() {
			// public void mousePressed(java.awt.event.MouseEvent e) {
			// if (e.getButton() == MouseEvent.BUTTON3
			// && nnInputTable.getSelectedRowCount() > 0) {
			// Point p = e.getPoint();
			// getNnInputPopupMenu().show(e.getComponent(), p.x, p.y);
			// }
			// }
			// });
			nnInputTable.addKeyListener(new java.awt.event.KeyAdapter() {
				public void keyTyped(java.awt.event.KeyEvent e) {
					if (e.getKeyChar() == KeyEvent.VK_DELETE) {
						deleteSelectedInputItem();
					}
				}
			});
			nnInputTable.setDefaultRenderer(BufferedImage.class,
					new ImageTableCellRenderer());
			nnInputTable.add(getNnInputPopupMenu());
		}
		return nnInputTable;
	}

	/**
	 * This method initializes momentumSpinner
	 * 
	 * @return javax.swing.JSpinner
	 */
	private JSpinner getMomentumSpinner() {
		if (momentumSpinner == null) {
			SpinnerNumberModel numberModel = new SpinnerNumberModel(0.30d,
					0.01d, 1.0d, 0.05);
			momentumSpinner = new JSpinner(numberModel);
		}
		return momentumSpinner;
	}

	/**
	 * This method initializes jSplitPane
	 * 
	 * @return javax.swing.JSplitPane
	 */
	private JSplitPane getJSplitPane() {
		if (jSplitPane == null) {
			jSplitPane = new JSplitPane();
			jSplitPane.setOneTouchExpandable(true);
			jSplitPane.setDividerSize(15);
			jSplitPane.setLeftComponent(getJPanel1());
			jSplitPane.setRightComponent(getJSplitPane1());
		}
		return jSplitPane;
	}

	/**
	 * This method initializes jPanel2
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel2() {
		if (jPanel2 == null) {
			GridBagConstraints gridBagConstraints110 = new GridBagConstraints();
			gridBagConstraints110.gridx = 0;
			gridBagConstraints110.gridwidth = 2;
			gridBagConstraints110.gridy = 5;
			GridBagConstraints gridBagConstraints31 = new GridBagConstraints();
			gridBagConstraints31.gridx = 0;
			gridBagConstraints31.gridwidth = 2;
			gridBagConstraints31.gridheight = 15;
			gridBagConstraints31.weighty = 5.0;
			gridBagConstraints31.gridy = 10;
			jLabel7 = new JLabel();
			jLabel7.setText("     ");
			jPanel2 = new JPanel();
			jPanel2.setLayout(new GridBagLayout());

			timeLabel = new JLabel();
			timeLabel.setText("0秒");
			jLabel6 = new JLabel();
			jLabel6.setText("时间");
			jLabel8 = new JLabel();
			jLabel8.setText("错误率");
			errorRateLabel = new JLabel();
			errorRateLabel.setText("0%");
			circleLabel = new JLabel();
			circleLabel.setText("0");
			jLabel5 = new JLabel();
			jLabel5.setText("已完成周期");
			jLabel4 = new JLabel();
			jLabel4.setText("当前进度");
			jLabel3 = new JLabel();
			jLabel3.setText("动量因子:");
			jLabel2 = new JLabel();
			jLabel2.setText("学习速率:");
			jLabel1 = new JLabel();
			jLabel1.setText("训练次数:");
			jLabel = new JLabel();
			jLabel.setText("网络类型:");

			GridBagConstraints gridBagConstraints20 = new GridBagConstraints();
			gridBagConstraints20.anchor = GridBagConstraints.WEST;
			gridBagConstraints20.gridx = 1;
			gridBagConstraints20.gridy = 9;
			gridBagConstraints20.insets = new Insets(0, 5, 0, 0);
			GridBagConstraints gridBagConstraints13 = new GridBagConstraints();
			gridBagConstraints13.anchor = GridBagConstraints.EAST;
			gridBagConstraints13.gridy = 9;
			gridBagConstraints13.gridx = 0;
			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
			gridBagConstraints6.anchor = GridBagConstraints.WEST;
			gridBagConstraints6.gridx = 1;
			gridBagConstraints6.gridy = 8;
			gridBagConstraints6.insets = new Insets(0, 5, 0, 0);
			GridBagConstraints gridBagConstraints19 = new GridBagConstraints();
			gridBagConstraints19.anchor = GridBagConstraints.EAST;
			gridBagConstraints19.gridy = 8;
			gridBagConstraints19.gridx = 0;
			GridBagConstraints gridBagConstraints18 = new GridBagConstraints();
			gridBagConstraints18.anchor = GridBagConstraints.WEST;
			gridBagConstraints18.gridx = 1;
			gridBagConstraints18.gridy = 7;
			gridBagConstraints18.insets = new Insets(0, 5, 0, 0);
			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
			gridBagConstraints4.anchor = GridBagConstraints.EAST;
			gridBagConstraints4.gridy = 7;
			gridBagConstraints4.gridx = 0;
			GridBagConstraints gridBagConstraints17 = new GridBagConstraints();
			gridBagConstraints17.fill = GridBagConstraints.HORIZONTAL;
			gridBagConstraints17.gridwidth = 1;
			gridBagConstraints17.gridx = 1;
			gridBagConstraints17.gridy = 6;
			gridBagConstraints17.insets = new Insets(5, 10, 10, 10);
			GridBagConstraints gridBagConstraints16 = new GridBagConstraints();
			gridBagConstraints16.anchor = GridBagConstraints.EAST;
			gridBagConstraints16.gridy = 6;
			gridBagConstraints16.gridx = 0;
			GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
			gridBagConstraints11.fill = GridBagConstraints.HORIZONTAL;
			gridBagConstraints11.gridwidth = 2;
			gridBagConstraints11.gridx = 0;
			gridBagConstraints11.gridy = 4;
			gridBagConstraints11.insets = new Insets(5, 0, 0, 0);
			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
			gridBagConstraints3.anchor = GridBagConstraints.WEST;
			gridBagConstraints3.gridx = 1;
			gridBagConstraints3.gridy = 3;
			gridBagConstraints3.insets = new Insets(5, 5, 0, 0);
			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
			gridBagConstraints2.anchor = GridBagConstraints.EAST;
			gridBagConstraints2.gridx = 0;
			gridBagConstraints2.gridy = 3;
			gridBagConstraints2.insets = new Insets(5, 0, 0, 0);
			GridBagConstraints gridBagConstraints15 = new GridBagConstraints();
			gridBagConstraints15.anchor = GridBagConstraints.WEST;
			gridBagConstraints15.gridx = 1;
			gridBagConstraints15.gridy = 2;
			gridBagConstraints15.insets = new Insets(0, 5, 0, 0);
			GridBagConstraints gridBagConstraints12 = new GridBagConstraints();
			gridBagConstraints12.anchor = GridBagConstraints.EAST;
			gridBagConstraints12.gridy = 2;
			gridBagConstraints12.gridx = 0;
			GridBagConstraints gridBagConstraints7 = new GridBagConstraints();
			gridBagConstraints7.anchor = GridBagConstraints.WEST;
			gridBagConstraints7.gridx = 1;
			gridBagConstraints7.gridy = 1;
			gridBagConstraints7.insets = new Insets(5, 5, 0, 0);
			GridBagConstraints gridBagConstraints10 = new GridBagConstraints();
			gridBagConstraints10.anchor = GridBagConstraints.EAST;
			gridBagConstraints10.gridx = 0;
			gridBagConstraints10.gridy = 1;
			gridBagConstraints10.insets = new Insets(5, 0, 0, 0);
			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
			gridBagConstraints1.anchor = GridBagConstraints.CENTER;
			gridBagConstraints1.insets = new Insets(5, 5, 0, 0);
			gridBagConstraints1.gridx = 1;
			gridBagConstraints1.gridy = 0;
			gridBagConstraints1.weighty = 0.0;
			gridBagConstraints1.fill = GridBagConstraints.HORIZONTAL;
			GridBagConstraints gridBagConstraints = new GridBagConstraints();
			gridBagConstraints.anchor = GridBagConstraints.CENTER;
			gridBagConstraints.gridx = 0;
			gridBagConstraints.gridy = 0;
			gridBagConstraints.fill = GridBagConstraints.NONE;
			gridBagConstraints.ipadx = 0;
			gridBagConstraints.ipady = 0;
			gridBagConstraints.weighty = 0.0;
			gridBagConstraints.insets = new Insets(0, 0, 0, 0);

			jPanel2.add(jLabel, gridBagConstraints);
			jPanel2.add(getNnTypeComboBox(), gridBagConstraints1);
			jPanel2.add(jLabel2, gridBagConstraints10);
			jPanel2.add(getLearningRateSpinner(), gridBagConstraints7);
			jPanel2.add(jLabel3, gridBagConstraints12);
			jPanel2.add(getMomentumSpinner(), gridBagConstraints15);
			jPanel2.add(jLabel1, gridBagConstraints2);
			jPanel2.add(getEpochsSpinner(), gridBagConstraints3);
			jPanel2.add(getJPanel(), gridBagConstraints11);
			jPanel2.add(jLabel4, gridBagConstraints16);
			jPanel2.add(getNnProgressBar(), gridBagConstraints17);
			jPanel2.add(jLabel5, gridBagConstraints4);
			jPanel2.add(circleLabel, gridBagConstraints18);
			jPanel2.add(jLabel8, gridBagConstraints19);
			jPanel2.add(errorRateLabel, gridBagConstraints6);
			jPanel2.add(jLabel6, gridBagConstraints13);
			jPanel2.add(timeLabel, gridBagConstraints20);
			jPanel2.add(jLabel7, gridBagConstraints31);
			jPanel2.add(getJPanel5(), gridBagConstraints110);
		}
		return jPanel2;
	}

	/**
	 * This method initializes jSplitPane1
	 * 
	 * @return javax.swing.JSplitPane
	 */
	private JSplitPane getJSplitPane1() {
		if (jSplitPane1 == null) {
			jSplitPane1 = new JSplitPane();
			jSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
			jSplitPane1.setOneTouchExpandable(true);
			jSplitPane1.setDividerSize(15);
			jSplitPane1.setDividerLocation(250);
			jSplitPane1.setBottomComponent(getJPanel4());
			jSplitPane1.setTopComponent(getJPanel3());
		}
		return jSplitPane1;
	}

	/**
	 * This method initializes jPanel3
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel3() {
		if (jPanel3 == null) {
			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
			gridBagConstraints5.fill = GridBagConstraints.BOTH;
			gridBagConstraints5.gridwidth = 2;
			gridBagConstraints5.gridx = -1;
			gridBagConstraints5.gridy = -1;
			gridBagConstraints5.weightx = 0.0;
			gridBagConstraints5.weighty = 0.0;
			gridBagConstraints5.gridheight = 9;
			jPanel3 = new JPanel();
			jPanel3.setLayout(new BorderLayout());
			jPanel3.add(getJScrollPane11(), BorderLayout.CENTER);
		}
		return jPanel3;
	}

	/**
	 * This method initializes jPanel4
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel4() {
		if (jPanel4 == null) {
			GridBagConstraints gridBagConstraints9 = new GridBagConstraints();
			gridBagConstraints9.fill = GridBagConstraints.BOTH;
			gridBagConstraints9.gridwidth = 2;
			gridBagConstraints9.gridx = -1;
			gridBagConstraints9.gridy = -1;
			gridBagConstraints9.weightx = 1.0;
			gridBagConstraints9.weighty = 1.0;
			gridBagConstraints9.gridheight = 5;
			jPanel4 = new JPanel();
			jPanel4.setLayout(new BorderLayout());
			jPanel4.add(getJScrollPane(), BorderLayout.CENTER);
		}
		return jPanel4;
	}

	/**
	 * This method initializes jPanel1
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel1() {
		if (jPanel1 == null) {
			jPanel1 = new JPanel();
			jPanel1.setLayout(new BorderLayout());
			jPanel1.add(getJPanel2(), BorderLayout.CENTER);
		}
		return jPanel1;
	}

	/**
	 * This method initializes continueButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getContinueButton() {
		if (continueButton == null) {
			continueButton = new JButton();
			continueButton.setText("继续");
			continueButton.setEnabled(false);
			continueButton
					.addActionListener(new java.awt.event.ActionListener() {
						public void actionPerformed(java.awt.event.ActionEvent e) {
							model.getNN().continueRun();
							startButton.setEnabled(false);
							pauseButton.setEnabled(true);
							continueButton.setEnabled(false);
							setNNControlState(false);
						}
					});
		}
		return continueButton;
	}

	/**
	 * This method initializes pauseButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getPauseButton() {
		if (pauseButton == null) {
			pauseButton = new JButton();
			pauseButton.setText("暂停");
			pauseButton.setEnabled(false);
			pauseButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					model.getNN().pause();
					pauseButton.setEnabled(false);
					continueButton.setEnabled(true);
					setNNControlState(true);
				}
			});
		}
		return pauseButton;
	}

	/**
	 * This method initializes addNoiseButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getAddNoiseButton() {
		if (addNoiseButton == null) {
			addNoiseButton = new JButton();
			addNoiseButton.setText("添加噪声");
			addNoiseButton
					.addActionListener(new java.awt.event.ActionListener() {
						public void actionPerformed(java.awt.event.ActionEvent e) {
							getModel().getNN().addNoise();
						}
					});
		}
		return addNoiseButton;
	}

	/**
	 * This method initializes randomButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getRandomButton() {
		if (randomButton == null) {
			randomButton = new JButton();
			randomButton.setText("随机状态");
			randomButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					getModel().getNN().randomize();
				}
			});
		}
		return randomButton;
	}

	/**
	 * This method initializes jPanel5
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJPanel5() {
		if (jPanel5 == null) {
			GridBagConstraints gridBagConstraints24 = new GridBagConstraints();
			gridBagConstraints24.gridx = 1;
			gridBagConstraints24.gridy = 1;
			GridBagConstraints gridBagConstraints25 = new GridBagConstraints();
			gridBagConstraints25.gridx = 0;
			gridBagConstraints25.gridy = 1;
			GridBagConstraints gridBagConstraints23 = new GridBagConstraints();
			gridBagConstraints23.gridx = -1;
			gridBagConstraints23.gridy = -1;
			GridBagConstraints gridBagConstraints21 = new GridBagConstraints();
			gridBagConstraints21.gridx = -1;
			gridBagConstraints21.gridy = -1;
			jPanel5 = new JPanel();
			jPanel5.setLayout(new GridBagLayout());
			jPanel5.add(getAddNoiseButton(), gridBagConstraints21);
			jPanel5.add(getRandomButton(), gridBagConstraints23);
			jPanel5.add(getResetInputButton(), gridBagConstraints25);
			jPanel5.add(getOutputButton(), gridBagConstraints24);
		}
		return jPanel5;
	}

	/**
	 * This method initializes resetInputButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getResetInputButton() {
		if (resetInputButton == null) {
			resetInputButton = new JButton();
			resetInputButton.setText("重置输入");
			resetInputButton
					.addActionListener(new java.awt.event.ActionListener() {
						public void actionPerformed(java.awt.event.ActionEvent e) {
							nnInputTableModel.reload();
							model.getNN().setNNInput(
									nnInputTableModel.getNnInput());
						}

					});
		}
		return resetInputButton;
	}

	/**
	 * This method initializes outputButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getOutputButton() {
		if (outputButton == null) {
			outputButton = new JButton();
			outputButton.setText("输出结果");
			outputButton.setEnabled(false);
			outputButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					outputButton.setEnabled(false);
					new Thread(new Runnable() {
						public void run() {
							try {
								final TrainResult trainResult = model.getNN()
										.getTrainResult();
								model.setTrainResult(trainResult);
								jTable.setModel(new DefaultTableModel());
								jTable.setModel(model.getNnTableModel());
								//jTable.updateUI();

								NNRecognizer tokenRecognizer = new NNRecognizer();
								tokenRecognizer.setTrainResult(trainResult);
								AppModel.getInstance().setTokenRecognizer(
										tokenRecognizer);
							} finally {
								outputButton.setEnabled(true);
							}
						}
					}).start();

				}
			});
		}
		return outputButton;
	}

	/**
	 * This method initializes nnInputPopupMenu
	 * 
	 * @return javax.swing.JPopupMenu
	 */
	private JPopupMenu getNnInputPopupMenu() {
		if (nnInputPopupMenu == null) {
			nnInputPopupMenu = new JPopupMenu();
			nnInputPopupMenu.add(getJMenuItem());
		}
		return nnInputPopupMenu;
	}

	private void deleteSelectedInputItem() {
		int count = nnInputTable.getSelectedRowCount();
		if (count == 0) {
			return;
		}
		int[] rowes = nnInputTable.getSelectedRows();
		for (int i = rowes.length - 1; i >= 0; i--) {
			nnInputTableModel.removeRow(rowes[i]);
		}
		nnInputTable.updateUI();
	}

	/**
	 * This method initializes jMenuItem
	 * 
	 * @return javax.swing.JMenuItem
	 */
	private JMenuItem getJMenuItem() {
		if (jMenuItem == null) {
			jMenuItem = new JMenuItem();
			jMenuItem.setText("删除当前行");
			jMenuItem.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					deleteSelectedInputItem();
					nnInputPopupMenu.setVisible(false);
				}
			});
		}
		return jMenuItem;
	}

	public static void main(String[] args) {
		TrainerPanel panel = new TrainerPanel();
		PanelLauncher launcher = new PanelLauncher(panel);
		launcher.show(400, 300);
	}

	private class StartTrainThread extends Thread {

		public StartTrainThread() {
		}

		public void run() {
			NNInput nnInput = nnInputTableModel.getNnInput();
			if (nnInput == null) {
				nnInputTableModel.reload();
				nnInput = nnInputTableModel.getNnInput();
			}
			startTime = System.currentTimeMillis();

			TrainerPanelModel model = getModel();

			NN nn = model.getNN();
			nn.setNNInput(nnInput);
			nn.setNeuralNetListener(TrainerPanel.this);

			nn.run();
		}
	}

	private long startTime;

	private JSplitPane jSplitPane = null;

	private JPanel jPanel2 = null;

	private JSplitPane jSplitPane1 = null;

	private JPanel jPanel3 = null;

	private JPanel jPanel4 = null;

	private JPanel jPanel1 = null;

	private JLabel jLabel7 = null;

	private JButton continueButton = null;

	private JButton pauseButton = null;

	private JButton addNoiseButton = null;

	private JButton randomButton = null;

	private JPanel jPanel5 = null;

	private JButton resetInputButton = null;

	private JButton outputButton = null;

	private JPopupMenu nnInputPopupMenu = null;

	private JMenuItem jMenuItem = null;

	public void cicleTerminated(NeuralNetEvent e) {
		final Monitor monitor = (Monitor) e.getSource();
		finishedPatterns++;
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				nnProgressBar.setMaximum(monitor.getTotCicles());
				nnProgressBar.setValue(finishedPatterns);
				circleLabel.setText(String.valueOf(finishedPatterns));
				String time = (System.currentTimeMillis() - startTime) * 1.0
						/ 1000 + "秒";
				timeLabel.setText(time);
			}

		});
	}

	public void errorChanged(NeuralNetEvent e) {
		Monitor m = (Monitor) e.getSource();
		errorRateLabel.setText(m.getGlobalError() * 100 + "%");
	}

	public void netStarted(NeuralNetEvent e) {

	}

	public void netStopped(NeuralNetEvent e) {
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				startButton.setEnabled(true);
				setNNControlState(true);
			}

		});
	}

	public void netStoppedError(NeuralNetEvent e, final String error) {
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {
				JOptionPane.showMessageDialog(TrainerPanel.this, error);
			}

		});
	}

}
